Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

png: Make bytemuck optional #138

Merged
merged 1 commit into from
Sep 13, 2023
Merged

png: Make bytemuck optional #138

merged 1 commit into from
Sep 13, 2023

Conversation

not-fl3
Copy link
Contributor

@not-fl3 not-fl3 commented Sep 6, 2023

For zune-png, bytemuck, the crate, is used just once, to convert u16 slice to u8 slice.

This PR does not alter the default behavior: this conversion is still going through the crate.
But without bytemuck feature it is just slice.align_to_mut::<u8>().

I tested the new code on the hdr PNG triggering this codepath and it all seems to still work fine.

New function looks ugly, but, unfortunately, attributes on regions are not yet stable and that was the simplest workaround I've seen.

I do have a PR for the log in queue :D Not like bytemuck and log are that big, but having them under a feature-flag would be really nice!

@etemesi254
Copy link
Owner

Hi, thanks for your contribution.

I don't see any problem with the code, but pinging @Shnatsel in case there is some memory bug introduced here.

I'm not a fan of nested functions so I'd rather the function be moved to be a standalone (probably in utils.h)

But in case there are no bugs, we should probably drop the bytemuck dependency all together

@Shnatsel
Copy link
Contributor

Shnatsel commented Sep 7, 2023

Looks good to me, incl. dropping bytemuck entirely.

I'd like to see a more detailed safety comment. Calling out that alignment of u8 always less than u16, and both types are valid for all bit patterns with no lifetimes so a transmute is fine (align_to is essentially a transmute).

Also we should leave a comment that if more such conversions are needed, bytemuck should be brought back. It's only dropped because this conversion is exceedingly trivial.

@@ -777,7 +777,22 @@ impl<T: ZReaderTrait> PngDecoder<T> {
{
&mut out_u8
} else {
let (a, b, c) = bytemuck::pod_align_to_mut::<u16, u8>(&mut out_u16);
#[inline(always)]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be greatly simplified by just dropping all of this alignment logic. Converting a 16 slice to a u8 slice is always correct because the alignment of the target is smaller. Just casting it by hand and doubling the size is easier to understand than the align_to_mut dance imo.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bytemuck https://docs.rs/bytemuck/latest/bytemuck/fn.bytes_of_mut.html function could be used but if bytemuck is optional it probably makes more sense to just drop it

@not-fl3
Copy link
Contributor Author

not-fl3 commented Sep 7, 2023

Looks good to me, incl. dropping bytemuck entirely.

I'd like to see a more detailed safety comment. Calling out that alignment of u8 always less than u16, and both types are valid for all bit patterns with no lifetimes so a transmute is fine (align_to is essentially a transmute).

Also we should leave a comment that if more such conversions are needed, bytemuck should be brought back. It's only dropped because this conversion is exceedingly trivial.

I personally prefer transmute to align_to, because align_to behavior is not specified How exactly the slice is split up is not specified and for the u16->u8 case transmute looks a lot more transparent. To be honest, I do not really understand what the docs mean by not specified. According to reddit, its transmute in debug/release, but not a transmute and a random split under miri?

But this change brakes the promise of Safety: No unsafe code, with the sole exception of SIMD intrinsics which currently require unsafe. I thought that having bytemuck by default is a good compromise: still no unsafe in the zune codebase involved by default, but possible to avoid extra deps.

a879297 (attached the commit for reference, would rather remove it later on rebase or something)

pub fn convert_u16_to_u8_slice(slice: &mut [u16]) -> &mut [u8] {
// Converting a u16 slice to a u8 slice is always correct because
// the alignment of the target is smaller.
unsafe { std::slice::from_raw_parts_mut(slice.as_ptr() as *mut u8, slice.len() * 2) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if slice.len() * 2 overflows?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it can but there should be a comment explaining why it cannot

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also thought it can not, but fixed it with a checked_mul.

@etemesi254
Copy link
Owner

But this change brakes the promise of Safety: No unsafe code, with the sole exception of SIMD intrinsics which currently require unsafe. I thought that having bytemuck by default is a good compromise: still no unsafe in the zune codebase involved by default, but possible to avoid extra deps.

Fine by me, it's one well documented line

@etemesi254
Copy link
Owner

I do have a PR for the log in queue :D Not like bytemuck and log are that big, but having them under a feature-flag would be really nice!

For this, btw I'd love if it went to zune-core, maybe have a macro like zune_warn! which expands to log::warn! if a log feature is included in zune-core otherwise expands to nothing, then this can be used to disable logging for all libraries with one swoop, just an opinion :).

@etemesi254
Copy link
Owner

@not-fl3 Is this okay to merge?

Converting a 16 slice to a u8 slice is always correct because the alignment of the target is smaller.
@not-fl3
Copy link
Contributor Author

not-fl3 commented Sep 11, 2023

@not-fl3 Is this okay to merge?

I believe so! Rebased out my first try commit.

@etemesi254 etemesi254 merged commit 73bb53e into etemesi254:dev Sep 13, 2023
@etemesi254
Copy link
Owner

Thank you, will make a breaking release probably over the weekend with the changes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants